﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;
using System.ComponentModel;
using BEPUphysics.Entities;
using BEPUphysics.MathExtensions;

namespace The_LarX
{
    public class BepuActorPlayer : Component, ICloneable
    {
        /// <summary>
        /// O Actor que estamos usando
        /// </summary>
#if WINDOWS
        [Category("Geral")]
        [Description("O Actor  que estamos usando")]
#endif
        public Actor Actor
        {
            get { return actor; }
            set { actor = value; }
        }
        protected Actor actor;

        protected Renderer renderer;
        /// <summary>
        /// The RenderType Used
        /// </summary>
        public Renderer Renderer
        {
            get { return renderer; }
            set
            {
                renderer = value;
            }
        }

        public BepuEntity Entity;

        public bool ApplyRotation { get; set; }
        
        public BepuActorPlayer(BepuEntity Entity, Actor Actor, Renderer Renderer, GameScreen Screen)
            : base(Screen)
        {
            this.Actor = Actor;
            this.Actor.ComponentParent = this;
            this.Renderer = Renderer;
            //this.Actor.Parent = this;
            this.Entity = Entity;
            //this.Entity.Actor = Actor;
            this.ApplyRotation = true;
            // Manda o Actor para o sistema de Renderização
            if (Renderer != null)
                Renderer.SubmitActor(Actor);

            this.Actor.RemoveActorFromRenderer = Renderer.RemoveActor;
            this.Actor.AddActorToRenderer = Renderer.SubmitActor;

            this.Actor.OnDisable += new EventHandler(Actor_OnDisable);
        }

        void Actor_OnDisable(object sender, EventArgs e)
        {
            base.DisableComponent();
        }

        public BepuActorPlayer()
            : base()
        {
        }

        public override void DisableComponent()
        {
            this.Actor.Disable();

            base.DisableComponent();
        }

        public override void Update()
        {
            Actor.Update();
            Entity.Update();

            if (Engine.PlayMode)
            {
                Actor.Position = Entity.Position;
                Actor.Scale = Entity.Scale;

                if (ApplyRotation)
                    Actor.RadiansRotation = Entity.Rotation;
                else
                    Entity.Rotation = Actor.RadiansRotation;
            }
            else
            {
                Entity.Entity.Position = Actor.Position;
                Entity.Entity.OrientationMatrix = Matrix3X3.CreateFromMatrix(Actor.RotationMatrix);
                Entity.Scale = Actor.Scale;
                Entity.Entity.LinearVelocity = Vector3.Zero;
                Entity.Entity.AngularVelocity = Vector3.Zero;
                Entity.Rotation = Actor.RadiansRotation;
            }            
            
            base.Update();
        }
        public override void Draw()
        {            
            // E chama o método Draw dele...
            Actor.Draw();

            base.Draw();
        }

        public override string ToString()
        {
            return Actor.Name + "Player";
        }

        public override void DrawOnDebugMode()
        {
            base.DrawOnDebugMode();

            //Engine.Render.DrawBoundingBox(Entity.Entity.BoundingBox, Color.Red, Renderer.Camera);
        }

        public override void SerializeData()
        {
            base.SerializeData();

            Actor.SerializeData(this.Data);
            Entity.SerializeData(this.Data);

            // Serializa o Tipo do Actor
            Data.AddData("ActorPlayer.Actor", this.Actor.GetType().ToString());
            Data.AddData("bEPUActorPlayer.Entity", this.Entity.GetType().ToString());
            Data.AddData("Renderer.Name", this.Renderer.Name);
        }
        public override void DeserializeData()
        {
            base.DeserializeData();

            Type ActorType = Type.GetType(Data.GetData<string>("ActorPlayer.Actor"));
            Actor Object = (Actor)System.Activator.CreateInstance(ActorType);

            this.Actor = Object;

            Actor.DeserializeData(Data);

            string rendererName = Data.GetData<string>("Renderer.Name");
            if (!string.IsNullOrEmpty(rendererName))
            {
                if (EngineSystem.Renderers.ContainsKey(rendererName))
                {
                    this.Renderer = EngineSystem.Renderers[rendererName];
                    this.Renderer.SubmitActor(Actor);
                }
            }
            else
            {
                if (EngineSystem.Renderers.Count > 0)
                {
                    this.Renderer = EngineSystem.Renderers.Values.First();
                    this.Renderer.SubmitActor(Actor);
                }
            }

            this.Actor.RemoveActorFromRenderer = Renderer.RemoveActor;
            this.Actor.AddActorToRenderer = Renderer.SubmitActor;
            this.Actor.OnDisable += new EventHandler(Actor_OnDisable);

            this.Actor.ComponentParent = this;

            Type EntityType = Type.GetType(Data.GetData<string>("bEPUActorPlayer.Entity"));
            BepuEntity EntityObject = (BepuEntity)System.Activator.CreateInstance(EntityType);
            this.Entity = EntityObject;
            this.Entity.DeserializeData(Data);

        }

        public override void SetToInitialState()
        {
            base.SetToInitialState();

            Actor.SetToInitialState();
        }

        public ICloneable Clone()
        {
            /*Type entityType = this.Entity.GetType();
            BepuEntity EntityObject = (BepuEntity)System.Activator.CreateInstance(entityType);

            Actor actor = (Actor)this.Actor.Clone();
            //BepuActorPlayer player = new BepuActorPlayer(EntityObject, 
            */
            throw new Exception();
        }
    }
}